﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Clipping.Infrastructure.Models;
using System.Text.RegularExpressions;
using System.Web;

namespace Clipping.Utils.SearchEngines
{
    public class SinaNews:ISearchEngine 
    {
        private Encoding _urlEncoding = Encoding.GetEncoding("gb2312");
        private Encoding _contentEncoding = Encoding.GetEncoding("gb2312");
        public void Parse(Uri url, string html, out List<News> news, out string nextPageUrl)
        {
            parse(html, out news, out nextPageUrl);
            if (!string.IsNullOrEmpty(nextPageUrl))
                nextPageUrl = constructAbsoluteUrl(url, nextPageUrl).OriginalString;
        }

        public Uri ConstructUrl(SearchObject searchObj)
        {
            return constructUrl(searchObj);
        }
        public void Search(SearchObject searchObj, IHtmlDownload downloader, out List<News> news, out string nextPageUrl)
        {
            var url = constructUrl(searchObj);
            string html = downloader.GetHtml(url);
            parse(html, out news, out nextPageUrl);
            if (!string.IsNullOrEmpty(nextPageUrl))
                nextPageUrl = constructAbsoluteUrl(url, nextPageUrl).OriginalString;
        }

        #region 私有方法
        private Uri constructUrl(SearchObject searchObj)
        {
            //Contract.Requires(searchObj != null);
            string url = string.Format("http://search.sina.com.cn/?q={0}&c=news&sort=time&{1}&{2}", HttpUtility.UrlEncode(searchObj.Keyword, this._urlEncoding), getSearchTypeQueryString(searchObj.SearchType), getSearchTimeQueryString(searchObj));
            return new Uri(url);
        }

        private Uri constructAbsoluteUrl(Uri baseUri, string url)
        {
            return UriHelper.ConstructAbsoluteUrl(baseUri, url);
        }

        private void parse(string html, out List<Infrastructure.Models.News> news, out string nextPageUrl)
        {
            news = new List<News>();
            nextPageUrl = null;
            HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
            doc.LoadHtml(html);
            var liNav = doc.CreateNavigator();
            var divSearchResult = liNav.Select("//div[@class='box-result clearfix']");

            while (divSearchResult.MoveNext())
            {
                News n = new News();

                var li = divSearchResult.Current;
                //取标题和链接
                var linkNode = li.SelectSingleNode("descendant::h2/a");
                if (linkNode != null)
                {
                    n.Title = linkNode.Value;
                    n.Title = System.Web.HttpUtility.HtmlDecode(n.Title);
                    n.Url = linkNode.GetAttribute("href", "");
                }

                //取时间及媒体
                var dtAndMediaNode = li.SelectSingleNode("descendant::span[@class='fgray_time']");
                if (dtAndMediaNode != null)
                {
                   string str= dtAndMediaNode.Value;
                   if (!string.IsNullOrEmpty(str))
                   {
                       int index = str.IndexOf(" ");
                       if (index > 0)
                       {
                           n.Media = str.Substring(0, index);
                           n.PubDate = str.Substring(index+1);
                       }
                   }
                }
                //取摘要
                var summaryNode = li.SelectSingleNode("descendant::p[@class='content']");
                if (summaryNode != null)
                {
                    n.Summary = summaryNode.Value;
                }

                news.Add(n);

            }

            //取下一页地址
            var nextPageNode = liNav.SelectSingleNode("//a[@title='下一页']");
            if (nextPageNode != null && nextPageNode.Value != null && nextPageNode.Value.Contains("下一页"))
            {
                nextPageUrl = nextPageNode.GetAttribute("href", "");
                if (!string.IsNullOrEmpty(nextPageUrl))
                    nextPageUrl = System.Web.HttpUtility.HtmlDecode(nextPageUrl);
            }
        }

        private string getSearchTypeQueryString(SearchType searchType)
        {
            if (searchType == SearchType.SearchInTitle)
                return "range=title";
            else
                return "range=all";
        }
        private string getSearchTimeQueryString(SearchObject searchObj)
        {
            if (searchObj is TimespanSearchObject)
            {
                TimespanSearchObject so = searchObj as TimespanSearchObject;
                return getSearchTimeQueryString(so.StartTime, so.EndTime);
            }
            else if (searchObj is PeriodSearchObject)
            {
                PeriodSearchObject so = searchObj as PeriodSearchObject;
                switch (so.SearchPeriod)
                {
                    case SearchPeriod.全部时间:
                        return "time=&stime=&etime=";
                    case SearchPeriod.最近1天:
                        return "time=d&stime=&etime=";
                    case SearchPeriod.最近1周:
                        return "time=w&stime=&etime=";
                    case SearchPeriod.最近1月:
                        return "time=m&stime=&etime=";
                    case SearchPeriod.最近2天:
                        return getSearchTimeQueryString(DateTime.Now.AddDays(-2), DateTime.Now);
                    case SearchPeriod.最近3天:
                        return getSearchTimeQueryString(DateTime.Now.AddDays(-3), DateTime.Now);
                    case SearchPeriod.最近2月:
                        return getSearchTimeQueryString(DateTime.Now.AddMonths(-2), DateTime.Now);
                    case SearchPeriod.最近3月:
                        return getSearchTimeQueryString(DateTime.Now.AddMonths(-3), DateTime.Now);
                    case SearchPeriod.最近1年:
                        return getSearchTimeQueryString(DateTime.Now.AddYears(-1), DateTime.Now);
                    default:
                        return "time=&stime=&etime=";
                }
            }
            else
                return null;
        }
        private string getSearchTimeQueryString(DateTime startTime, DateTime endTime)
        {
            return string.Format("time=custom&stime={0:yyyy-MM-dd}&etime={1:yyyy-MM-dd}", startTime, endTime);

        }

        #endregion

        #region 属性

        public string Name
        {
            get { return "新浪新闻搜索"; }
        }
        public Encoding ContentEncoding
        {
            get { return _contentEncoding; }
        }
        #endregion




      
    }
}
